package com.lik888.web1.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.lik888.web1.OSS.AliOssProperties;
import lombok.Data;
import lombok.NoArgsConstructor; // 替换@AllArgsConstructor为@NoArgsConstructor
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.ByteArrayInputStream;
import java.util.Objects;

@Data
@NoArgsConstructor // 生成无参构造方法，让Spring能通过@Autowired注入属性
@Slf4j
@Component
public class AliOssUtil {

    // 仅保留@Autowired，Spring会自动注入AliOssProperties
    @Autowired
    private   AliOssProperties aliyunOSSProperties;

    /**
     * 文件上传
     *
     * @param bytes     文件字节数组（如MultipartFile.getBytes()）
     * @param objectName OSS中的文件路径+文件名（如"goods/20240915/abc.jpg"）
     * @return 文件在OSS中的访问URL
     */
    public String upload(byte[] bytes, String objectName) {
        // 1. 校验AliOssProperties是否注入成功，避免空指针
        if (Objects.isNull(aliyunOSSProperties)) {
            throw new RuntimeException("AliOssProperties 注入失败，请检查配置类是否正确注册");
        }

        // 2. 提取配置参数，并校验非空
        String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();
        String accessKeyId = aliyunOSSProperties.getAccessKeyId();
        String accessKeySecret = aliyunOSSProperties.getAccessKeySecret();

        // 校验核心参数，为空则抛出明确异常（方便定位配置问题）
        if (!StringUtils.hasText(endpoint)) {
            throw new IllegalArgumentException("OSS配置：endpoint不能为空，请检查application.yaml中的aliyun.oss.endpoint");
        }
        if (!StringUtils.hasText(bucketName)) {
            throw new IllegalArgumentException("OSS配置：bucketName不能为空，请检查application.yaml中的aliyun.oss.bucketName");
        }
        if (!StringUtils.hasText(accessKeyId)) {
            throw new IllegalArgumentException("OSS配置：accessKeyId不能为空，请检查application.yaml中的aliyun.oss.accessKeyId");
        }
        if (!StringUtils.hasText(accessKeySecret)) {
            throw new IllegalArgumentException("OSS配置：accessKeySecret不能为空，请检查application.yaml中的aliyun.oss.accessKeySecret");
        }
        // 校验文件字节数组和目标文件名非空
        if (Objects.isNull(bytes) || bytes.length == 0) {
            throw new IllegalArgumentException("上传文件不能为空");
        }
        if (!StringUtils.hasText(objectName)) {
            throw new IllegalArgumentException("OSS目标文件名不能为空");
        }

        OSS ossClient = null;
        try {
            // 3. 创建OSS客户端（此时参数已确保非空，避免URI空指针）
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

            // 4. 上传文件到OSS
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
            log.info("文件上传成功，OSS中的文件名：{}", objectName);

            // 5. 拼接文件访问URL（注意：endpoint需去除http/https前缀，避免URL重复协议）
            String endpointWithoutProtocol = endpoint.replaceFirst("^https?://", ""); // 去掉"http://"或"https://"
            StringBuilder urlBuilder = new StringBuilder("https://");
            urlBuilder.append(bucketName)
                    .append(".")
                    .append(endpointWithoutProtocol)
                    .append("/")
                    .append(objectName);

            String fileUrl = urlBuilder.toString();
            log.info("文件访问URL：{}", fileUrl);
            return fileUrl;

        } catch (OSSException oe) {
            // OSS服务端异常（如权限不足、bucket不存在）
            log.error("OSS服务端异常：错误码={}, 错误信息={}, RequestId={}",
                    oe.getErrorCode(), oe.getErrorMessage(), oe.getRequestId(), oe);
            throw new RuntimeException("文件上传到OSS失败（服务端异常）", oe);
        } catch (ClientException ce) {
            // OSS客户端异常（如网络不可达、endpoint错误）
            log.error("OSS客户端异常：错误信息={}", ce.getMessage(), ce);
            throw new RuntimeException("文件上传到OSS失败（客户端异常，检查网络或endpoint）", ce);
        } finally {
            // 6. 关闭OSS客户端，避免资源泄漏
            if (ossClient != null) {
                ossClient.shutdown();
                log.debug("OSS客户端已关闭");
            }
        }
    }
}